using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Xml;
using System.Collections.Specialized;
using SharpObjects.Shared;
using SharpObjects.Configuration;

namespace SharpObjects.Data
{
	/// <summary>
	/// IDb allows an application to work with a database without knowing the implementation details.
	/// This inteface must be implemented by a Database class, which knows specific database implementation.
	/// The Database class will be loaded from a DLL and an object created.
	/// </summary>
	public interface IDb : IDisposable
	{
	    void Initialize(string connectionString);

		IDbCommand CreateQueryCommand(string sSql);

		// template has {n} replacements for params; descriptor defines types, directions, sizes e.t.c.
		// for example, template: "select * from my_table where product_id={0}".
		// parameter, passed to the function has the name: "PRODUCT_ID"
		// the {0} sequence will be replaced with :PRODUCT_ID for Oracle and with @PRODUCT_ID for SQL Server
		/*
			<param_descriptors>
				<param_descriptor name=":PROCESS_ID" type="Int32" direction="Input" />
				<param_descriptor name=":DESCRIPTION" type="String" direction="Input" nullable="true" precision="0" scale="0" size="200" source_column=":DESCRIPTION" row_version="Current"/>
			</param_descriptors>
		*/
		IDbCommand CreateQueryCommand(string sSqlTemplate, string sParamDescriptorXml, params object [] values);
		IDbCommand CreateQueryCommand(string sSqlTemplate, params IDbParameterDescriptor [] parameters);
		IDbCommand CreateQueryCommand(string sSqlTemplate, List<DbParameterDescriptor> parameters);

		IDbCommand CreateProcedureCommand(string sProcName, string sParamDescriptorXml, params object [] values);
		IDbCommand CreateProcedureCommand(string sProcName, params IDbParameterDescriptor [] parameters);

		void SetCommandParameterValue(IDbCommand cmd, int nParamId, object value);
		void SetCommandParameterValue(IDbCommand cmd, string sParamName, object value);

		// proc definition sql is a valid SQL create procedure statement
		IDbProcedureDescriptor ParseProcedureDefinitionSql(string sProcDefSql);
		IDbCommand CreateProcedureCommand(IDbProcedureDescriptor ProcDescriptor);

		IDbCommand CreateSelectTopNQueryCommand(string sTable, string sFieldList, string sWhere, string sEndOfQuery, int nCount);
		IDbCommand CreateSelectTopNQueryCommand(string sSelectStatement, int nCount);
		IDbCommand CreateSelectTopNQueryCommand(IDbCommand select, int nCount);

		IDbDataAdapter CreateDataAdapter(string sSelectSql);
		IDbDataAdapter CreateDataAdapter(string sSelectSql, bool bGenerateAllCommands);
		IDbDataAdapter CreateDataAdapter(IDbCommand SelectCmd);
		IDbDataAdapter CreateDataAdapter(IDbCommand SelectCmd, bool bGenerateAllCommands);
        void SetDataAdapterUpdateBatchSize(IDbDataAdapter da, int batchSize);
		
		IDbConnection Connection { get; }

		int ExecuteNonQuery(IDbCommand cmd);
		object ExecuteScalar(IDbCommand cmd);
		IDataReader ExecuteReader(IDbCommand cmd);

		DataSet FillDataSet(IDbDataAdapter adapter);
		DataSet FillDataSet(List<IDbDataAdapter> adapters);
		DataSet FillDataSet(IDbDataAdapter adapter, string sTable);
        DataSet FillDataSet(List<IDbDataAdapter> adapters, StringCollection tables);

		DataTable FillDataTable(IDbDataAdapter adapter);

		void UpdateDataSet(IDbDataAdapter adapter, DataSet ds);
		void UpdateDataSet(IDbDataAdapter adapter, string sTable, DataSet ds);
        void UpdateDataSet(List<IDbDataAdapter> adapters, StringCollection tables, DataSet ds);

		void UpdateDataTable(IDbDataAdapter adapter, DataTable dt);
		void UpdateDataRows(IDbDataAdapter adapter, DataRow [] rows);


		// used to retrieve appropriate string resources
		string ResourceVersion { get; }

		string ToDbDateTimeString(DateTime dt);
        string CurrentGmtDateFunction { get; } // returns database dependent expression that refers to the current GMT date and time
        string CurrentDateFunction { get; } // returns database dependent expression that refers to the current date and time
		string CurrentDatePlusDays(int nDays); // returns database dependent expression that adds specified number of days to the current date and time
		string CurrentDatePlusSeconds(int nSeconds); // returns database dependent expression that adds specified number of seconds to the current date and time
        DateTime MinDateTime();
        DateTime MaxDateTime();

		Int64 GenerateUniqueSequenceNumber(string sName); // uses database specific implementation to generate a unique sequential number

		string GetDataType(eDataType type);

		bool IsDbException(Exception ex);

		IDbTransaction Transaction { get; }

		IDbTransaction BeginTransaction();
		void CommitTransaction();
		void RollbackTransaction();

        bool CanBulkCopy { get; }
        long BulkCopy(string sDestinationTable, DataTable srcTable, int nTimeoutSec);
        long BulkCopy(string sDestinationTable, DataTable srcTable, int batchSize, int nTimeoutSec);
        long BulkCopy(string sDestinationTable, DataRowCollection rows, int nTimeoutSec);
        long BulkCopy(string sDestinationTable, DataRowCollection rows, int batchSize, int nTimeoutSec);
        long BulkCopy(string sDestinationTable, IDataReader reader, int nTimeoutSec);
        long BulkCopy(string sDestinationTable, IDataReader reader, int batchSize, int nTimeoutSec);

        string ParameterPrefix { get; }
    }



}
